package repository

import (
	"context"
	"fmt"
	"gin-vben-admin/internal/constant"
	"gin-vben-admin/internal/model"
	"gorm.io/gorm"
)

type SysMenuRepository interface {
	//PageList(ctx context.Context, req v1.SysRoleListReq) (int64, []*model.SysRole, error)
	Create(ctx context.Context, m *model.SysMenu) error
	Update(ctx context.Context, m *model.SysMenu, fields ...string) error
	GetById(ctx context.Context, menuId int64) (*model.SysMenu, error)
	GetListByPid(ctx context.Context, menuId int64) (menuList []*model.SysMenu, err error)
	ExistsPermission(ctx context.Context, permission string, excludeId int64) bool
	CreateMenuApis(ctx context.Context, m []*model.SysMenuApi) error
	GetCountByPid(ctx context.Context, pid int64) (total int64, err error)
	Delete(ctx context.Context, menuId int64) error
	DeleteMenuApi(ctx context.Context, menuId int64) error
	GetMenuActionByIds(ctx context.Context, menuIds []int64) (list []model.SysMenu, err error)
	UpdateIdPath(ctx context.Context, oldS, newS string) error
}

func NewSysMenuRepository(r *Repository) SysMenuRepository {
	return &sysMenuRepository{
		Repository: r,
	}
}

type sysMenuRepository struct {
	*Repository
}

func (r *sysMenuRepository) Create(ctx context.Context, m *model.SysMenu) error {
	return r.DB(ctx).Create(&m).Error
}

func (r *sysMenuRepository) Update(ctx context.Context, m *model.SysMenu, fields ...string) error {
	return r.DB(ctx).Select(fields).Updates(&m).Error
}

func (r *sysMenuRepository) CreateMenuApis(ctx context.Context, m []*model.SysMenuApi) error {
	return r.DB(ctx).Model(model.SysMenuApi{}).Create(&m).Error
}

func (r *sysMenuRepository) GetById(ctx context.Context, menuId int64) (m *model.SysMenu, err error) {
	err = r.DB(ctx).Where("menu_id = ?", menuId).First(&m).Error
	return
}

func (r *sysMenuRepository) GetCountByPid(ctx context.Context, pid int64) (total int64, err error) {
	err = r.DB(ctx).Model(model.SysMenu{}).Where("parent_id = ?", pid).Count(&total).Error
	return
}

func (r *sysMenuRepository) Delete(ctx context.Context, menuId int64) error {
	return r.DB(ctx).Delete(model.SysMenu{}, menuId).Error
}

func (r *sysMenuRepository) DeleteMenuApi(ctx context.Context, menuId int64) error {
	return r.DB(ctx).Where("menu_id = ?", menuId).Delete(model.SysMenuApi{}).Error
}

func (r *sysMenuRepository) ExistsPermission(ctx context.Context, permission string, excludeId int64) bool {
	var a int64
	var err error
	if excludeId > 0 {
		err = r.DB(ctx).Model(&model.SysMenu{}).Where("permission = ? and menu_id != ?", permission, excludeId).Count(&a).Error
	} else {
		err = r.DB(ctx).Model(&model.SysMenu{}).Where("permission = ?", permission).Count(&a).Error
	}
	if err == nil && a > 0 {
		return true
	}
	return false
}

// GetListByPid 获取菜单的子列表， pid=0时获取所有
func (r *sysMenuRepository) GetListByPid(ctx context.Context, menuId int64) (menuList []*model.SysMenu, err error) {
	menuList = make([]*model.SysMenu, 0)
	if menuId == 0 {
		err = r.DB(ctx).Order("sort asc").Find(&menuList).Error
	} else {
		menuModel := model.SysMenu{}
		err = r.DB(ctx).Where("menu_id = ?", menuId).First(&menuModel).Error
		if err != nil {
			return
		}
		err = r.DB(ctx).Where("id_path like ?", fmt.Sprintf("%s%d/", menuModel.IdPath, menuModel.MenuId)+"%").Order("sort asc").Find(&menuList).Error
	}
	return
}

// GetMenuActionByIds 根据菜单操作id批量获取菜单
func (r *sysMenuRepository) GetMenuActionByIds(ctx context.Context, menuIds []int64) (list []model.SysMenu, err error) {
	err = r.DB(ctx).Where("menu_type= ? and menu_id in (?) ", constant.MenuTypeAction, menuIds).Preload("Apis").Find(&list).Error
	return
}

func (r *sysMenuRepository) UpdateIdPath(ctx context.Context, oldS, newS string) error {
	return r.DB(ctx).Model(model.SysMenu{}).Where("id_path like ?", oldS+"%").
		UpdateColumn("id_path", gorm.Expr("REPLACE(`id_path`, ?, ?)", oldS, newS)).Error
}
